/*
	File:	video/FontManager.hpp
	Date:	2013-06-01
	Author:	Asteroth
*/


#ifndef __ZEN_FONT_MANAGER_HPP__
#define __ZEN_FONT_MANAGER_HPP__

#include <string>
#include <map>
#include <ft2build.h>
#include FT_FREETYPE_H

#include "TextureManager.hpp"
#include "Font.hpp"

namespace zen {

	namespace video {

		
		class FontManager {

		public:

			FontManager(TextureManager* textureManager);
			~FontManager();

			/**
			* Returns a font by id and size, if the font doesn't exist it will be created
			* from a font face with the same id and the specified size, and if the font face
			* with that id does not exist, will return null.
			*/
			PFont getFont(const std::string &id, int size);

			/**
			* Loads a font face from a file and registers it with the specified id.
			* Returns true if the font face has been loaded and ready for use.
			* This method will not load the font face if there already exists one
			* with the same id, even if the file and/or index is different.
			*/
			bool loadFontFace(const std::string &id, const std::string &fileName, int index = 0);

			/**
			* Removes a font face by id.
			* Returns true if the font was found and removed successfully.
			* This method should be invoked when all needed fonts of this font face were created,
			* the fonts are independent of their font faces after the creation.
			*/
			bool freeFontFace(const std::string &id);
			
			/**
			* Removes all font faces.
			* This method should be invoked when all needed fonts were created, the fonts are
			* independent of their font faces after the creation.
			*/
			void freeFontFaces();



		private:
			
			typedef std::pair<std::string, FT_Face> FontFacesEntry;
			typedef std::map<std::string, FT_Face> FontFaces;
			typedef FontFaces::iterator FontFacesIterator;
			typedef FontFaces::const_iterator FontFacesConstIterator;
			typedef std::pair<int, std::string> FontKey; // size and id
			typedef std::pair<FontKey, PFont> FontEntry;
			typedef std::map<FontKey, PFont> Fonts;
			typedef Fonts::iterator FontsIterator;
			typedef Fonts::const_iterator FontsConstIterator;

			TextureManager* textureManager;
			FT_Library fontLibrary;
			FontFaces fontFaces;
			Fonts fonts;

			FontManager();
			FontManager(const FontManager&);
			FontManager& operator = (const FontManager&);
			
			PFont createFont(const std::string &id, int size, FT_Face fontFace);

			static glm::ivec4 findGlyphPosition(int &nextY, int &posX, int &posY, const int &width, const int &height, const int &maxWidth, const int &maxHeight);

		};


		inline PFont FontManager::getFont(const std::string &id, int size) {
			FontsConstIterator fontIterator = fonts.find(FontKey(size, id));
			if (fontIterator != fonts.end())
				return fontIterator->second;
			FontFacesConstIterator faceIterator = fontFaces.find(id);
			if (faceIterator != fontFaces.end()) {
				PFont font = createFont(id, size, faceIterator->second);
				return font;
			}
			return PFont();
		}


	} // namespace video

} // namespace zen

#endif // __ZEN_FONT_MANAGER_HPP__